<?php

/*
 * This script belongs to Aspect PHP.
 *
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at your
 * option) any later version.
 *
 * This script is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN-
 * TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
 * General Public License for more details.
 */

/**
 * The aspectAdviceChain is used by around advices to handle the request to the
 * original method
 *
 * @package    aspectPhp
 * @subpackage lib
 * @author     gboisse
 */
class aspectAdviceChain {

    /** @var array The pointcuts to match */
    protected $pointcuts;
    /** @var integer The number of the next advice which will be invoked on a proceed() call */
    protected $adviceIndex = -1;
    /** @var integer The size of the advice chain */
    protected $adviceChainSize;

    /**
     * Creates the advice chain by matching the given pointcuts to the current
     * joinpoint
     *
     * @param array $pointcuts The pointcuts to match
     */
    public function __construct($pointcuts) {
        $this->pointcuts = $pointcuts;
        $this->adviceChainSize = count($pointcuts);
    }

    public function proceed(aspectJoinpoint $joinpoint) {

        for ($this->adviceIndex = ++$this->adviceIndex; $this->adviceIndex < $this->adviceChainSize; $this->adviceIndex++) {
            $pointcut = $this->pointcuts[$this->adviceIndex];
            if ($pointcut->matches($joinpoint)) {
                return aspectUtils::callFunction(
                        array(
                            aspectContainer::getInstance()->getAspectClassInstance($pointcut->getAspectClassName()),
                            $pointcut->getAdviceMethodName()
                        ),
                        array($joinpoint, $this));
            }
        }

        return aspectUtils::callFunction(
                array($joinpoint->getClassName(),
                    $joinpoint->getMethodName()
                ),
                $joinpoint->getMethodArgumentsForInvoke());
    }

}
